//
//  ViewController.swift
//  rxCoreLogic
//
//  Created by yq on 2020/12/7.
//
// AnonymousObservable : Producer
// combineLatest

import UIKit
import RxSwift
import RxCocoa
import EFMarkdown
import SwiftGifOrigin
/// rxSwift 操作符
enum RxOperatorType {
	
	case combinelaste
	case distinctUntilChanged
	case filter
	case flatMap
	case map
	case just
	case shareReplay
	case scan
	case binder
	case asyncSubject
	case publishSubject
	case replaySubject
	case behaviorSubject
	case elementAt
	case empty
	case flatMapLatest
	case merge
	case publish
	case startWith
	
	var title: String {
		switch self {
			case .asyncSubject:
				return "AsyncSubject"
			case .binder:
				return "Binder"
			case .combinelaste:
				return "CombineLaste"
			case .distinctUntilChanged:
				return "DistinctUntilChanged"
			case .filter:
				return "Filter"
			case .flatMap:
				return "FlatMap"
			case .just:
				return "Just"
			case .map:
				return "Map"
			case .publishSubject:
				return "PublishSubject"
			case .replaySubject:
				return "ReplaySubject"
			case .scan:
				return "Scan"
			case .shareReplay:
				return "ShareReplay"
			case .behaviorSubject:
				return "BehaviorSubject"
			case .elementAt:
				return "ElementAt"
			case .empty:
				return "Empty"
			case .flatMapLatest:
				return "FlatMapLatest"
			case .merge:
				return "Merge"
			case .publish:
				return "Publish"
			case .startWith:
				return "StartWith"
		}
	}
	
	var subTitle: String {
		switch self {
			case .distinctUntilChanged:
				return "distinctUntilChanged 操作符将阻止 Observable 发出相同的元素。如果后一个元素和前一个元素是相同的，那么这个元素将不会被发出来。如果后一个元素和前一个元素不相同，那么这个元素才会被发出来。"
			case .asyncSubject:
				return "“AsyncSubject 将在源 Observable 产生完成事件后，发出最后一个元素（仅仅只有最后一个元素），如果源 Observable 没有发出任何元素，只有一个完成事件。那 AsyncSubject 也只有一个完成事件。”"
			case .binder:
				return "\(title)“由于这个观察者是一个 UI 观察者，所以它在响应事件时，只会处理 next 事件”"
			case .flatMap:
				return "\(title)“操作符将源 Observable 的每一个元素应用一个转换方法，将他们转换成 Observables。 然后将这些 Observables 的元素合并之后再发送出来。”"
			case .map:
				return "\(title)“操作符将源 Observable 的每个元素应用你提供的转换方法，然后返回含有转换结果的 Observable。”"
			case .just:
				return "\(title)“操作符将某一个元素转换为 Observable。”"
			case .filter:
				return "\(title)“操作符将通过你提供的判定方法过滤一个 Observable”"
			case .scan:
				return "\(title)“操作符将对第一个元素应用一个函数，将结果作为第一个元素发出”"
			case .combinelaste:
				return "\(title)“操作符将多个 Observables 中最新的元素通过一个函数组合起来，然后将这个组合的结果发出来”"
			case .behaviorSubject:
				return "\(title)-“将 Observable 中最新的元素发送出来"
			case .publishSubject:
				return "\(title)“将对观察者发送订阅后产生的元素，而在订阅前发出的元素将不会发送给观察者”"
			case .replaySubject:
				return "\(title)“将对观察者发送全部的元素，无论观察者是何时进行订阅的”"
			case .shareReplay:
				return "\(title)“操作符将使得观察者共享源 Observable，并且缓存最新的 n 个元素，将这些元素直接发送给新的观察者”"
			case .elementAt:
				return "\(title)“操作符将拉取 Observable 序列中指定索引数的元素，然后将它作为唯一的元素发出。”"
			case .empty:
				return "\(title)“操作符将创建一个 Observable，这个 Observable 只有一个完成事件。”"
			case .flatMapLatest:
				return "\(title)“将 Observable 的元素转换成其他的 Observable，然后取这些 Observables 中最新的一个”"
			case .merge:
				return "\(title)将多个 Observables 合并成一个, 当某一个 Observable 发出一个元素时,他就将这个元素发出。"
			case .publish:
				return "\(title)“将 Observable 转换为可被连接的 Observable”"
			case .startWith:
				return "\(title)会在 observable 头部插入一些元素。"
		}
	}
	
}


class ViewController: YViewController {
	
	let datas: [RxOperatorType] = [
		.binder,
		.combinelaste,
		.distinctUntilChanged,
		.merge,
		.just,
		.map,
		.scan,
		.empty,
		.publish,
		.startWith,
		.elementAt,
		.filter,
		.flatMap,
		.flatMapLatest,
		.asyncSubject,
		.shareReplay,
		.publishSubject,
		.replaySubject,
		.behaviorSubject
	]
	
	
	private lazy var tableView: UITableView = {
		let tabView = UITableView(frame: view.bounds, style: .plain)
		tabView.delegate = self
		tabView.dataSource = self
		tabView.estimatedRowHeight  = 65
		tabView.rowHeight = UITableView.automaticDimension
		tabView.register(UINib(nibName: "\(YTableViewCell.self)", bundle: nil), forCellReuseIdentifier: "\(YTableViewCell.self)")
		tabView.tableFooterView = UIView()
		tabView.backgroundColor = .clear
		tabView.separatorStyle = .none
		
		let view = UIView(frame: UIScreen.main.bounds)
		let imgV = UIImageView()
		imgV.loadGif(name: "bg")
		imgV.frame = view.frame
		imgV.contentMode = .scaleAspectFill
		view.addSubview(imgV)
		
		tabView.backgroundView = view
		return tabView
	}()
	
	override func viewDidLoad() {
		super.viewDidLoad()
		
		setupUI()
		
		// - 创建序列
		// - 操作符: combineLaste
		// - 操作符: distinctUntilChanged
		// - 操作符: filter
		// - 操作符: flatMap
		// - 操作符: Map
		// - 操作符: just
		// - 操作符: shareReplay
		// - 操作符: scan
		// - 操作符: binder
		// - 辅助类型操作符: AsyncSubject
		// - 辅助类型操作符: PublishSubject
		// - 辅助类型操作符: ReplaySubject
		// - 辅助类型操作符: BehaviorSubject
		// - 操作符: elementAt
		// - 操作符: empty
		// - 操作符: flatMapLatest
		// - 操作符: merge
		// - 操作符: publish 不会发出元素, 直到 connect被调用
		// - 操作符: startWith 将一些元素插入到序列头部

	}
	
	
	override func viewWillAppear(_ animated: Bool) {
		super.viewWillAppear(animated)
		navigationController?.setNavigationBarHidden(true , animated: animated)
	}
	
	override func viewWillDisappear(_ animated: Bool) {
		super.viewWillDisappear(animated)
		navigationController?.setNavigationBarHidden(false, animated: animated)
	}
	
	
	func setupUI() {
		self.navigationItem.title = "RxSwift操作符"
		view.backgroundColor = .clear
		tableView.frame = view.bounds
		view.addSubview(tableView)
		
		configureNavgationBar(isTransparent: true)
	}
	
}


// =========================================== < 这是一条分割线 > =================================================

/**
* 大白话说专业术语
* - just( "0")  --> 相当于发送只有一个值 "0"一个事件
* - scan : 给每个元素应用这个, 并作为下一次的参数
* - publishSubject 订阅前发出的元素不打印
* - asyncSubject 拿到 onComplete 事件后, 发出最后一个元素
* - replaySubject buffSize 将订阅前的某些个元素发送出来
* - BehaviorSubject 比较常用的将最新的元素发送出来, ( 没有最新的元素, 就发出默认元素 )
*
*
*/

extension ViewController: UITableViewDelegate, UITableViewDataSource {
	
	func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
		return datas.count
	}
	
	func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
		let cell = tableView.dequeueReusableCell(withIdentifier: "\(YTableViewCell.self)", for: indexPath) as! YTableViewCell
		cell.selectionStyle = .none
		cell.titleLabel?.text = datas[indexPath.row].title
		cell.titleLabel?.font = UIFont(name: "Menlo", size: 17)
		cell.titleLabel?.textColor = .green
		cell.subTitleLabel?.text = datas[indexPath.row].subTitle
		return cell
	}
	
	func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
		tableView.deselectRow(at: indexPath, animated: true)
		
		let type = datas[indexPath.row]
		let vc = RXDetailViewController()
		vc.title = type.title
		vc.operatorType = type
		self.navigationController?.pushViewController(vc, animated: true)
	}
}
